package com.ai.bitcoin.service.impl;

import com.ai.bitcoin.bo.HtmlReportGenerateBO;
import com.ai.bitcoin.enums.HtmlReportEnum;
import com.ai.bitcoin.exception.BusinessException;
import com.ai.bitcoin.helper.GetQrcodeUrlHelper;
import com.ai.bitcoin.helper.HtmlReportParseHelper;
import com.ai.bitcoin.helper.JwtParseTokenHelper;
import com.ai.bitcoin.jpa.dao.BccSubCoinDao;
import com.ai.bitcoin.jpa.entity.BccNews;
import com.ai.bitcoin.jpa.entity.BccSubCoin;
import com.ai.bitcoin.jpa.entity.BccUser;
import com.ai.bitcoin.jpa.service.BccNewsService;
import com.ai.bitcoin.redis.service.BccRedisService;
import com.ai.bitcoin.service.HtmlReportService;
import com.ai.bitcoin.util.DateUtil;
import com.ai.bitcoin.vo.*;
import lombok.extern.slf4j.Slf4j;
import net.sf.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Future;

/**
 * Created by gulj on 2018/6/11.
 */
@Service
@Slf4j
public class HtmlReportServiceImpl implements HtmlReportService {


    @Autowired
    private JwtParseTokenHelper jwtParseTokenHelper;

    @Autowired
    private BccSubCoinDao subCoinDao;

    @Autowired
    private HtmlReportParseHelper htmlReportParseHelper;


    @Autowired
    private BccNewsService bccNewsService;

    @Autowired
    private BccRedisService bccRedisService;

    @Autowired
    private GetQrcodeUrlHelper getQrcodeUrlHelper;


    @Override
    public HtmlReportGenerateVO generate(HtmlReportGenerateBO htmlReportGenerateBO) throws BusinessException {
        //开始时间
        long startTime = System.currentTimeMillis();
        log.info("用户订阅报告生成开始：openId{}", htmlReportGenerateBO.getOpenId());
        // 定义响应体数据结构
        HtmlReportGenerateVO htmlReportGenerateVO = null;
        try {
            // 从redis中获取报告
            htmlReportGenerateVO = bccRedisService.getBitCoinReport("report_" + htmlReportGenerateBO.getReportDate() + "_" + htmlReportGenerateBO.getBccId());
            if (htmlReportGenerateVO == null) {
                log.error("【生成报告】 从redis中获取报告为空，bccId为：{}，reportDate为：{}", htmlReportGenerateBO.getBccId(), htmlReportGenerateBO.getReportDate());
                return null;
            }
            log.info("用户订阅报告 从redis中获取报告 结束：openId{},已耗时：{}s", htmlReportGenerateBO.getOpenId(), (System.currentTimeMillis() - startTime) / 1000.0);

            // 二维码链接
            Future<HtmlReportCoinQrcodeinfoVO> htmlReportCoinQrcodeinfoFuture = CompletableFuture.supplyAsync(() -> {
                long htmlReportCoinQrcodeinfoStartTime = System.currentTimeMillis();
                String qrcodeUrl = getQrcodeUrlHelper.getQrcodeUrl(htmlReportGenerateBO.getBccId(), htmlReportGenerateBO.getOpenId());
                HtmlReportCoinQrcodeinfoVO htmlReportCoinQrcodeinfoVO = new HtmlReportCoinQrcodeinfoVO();
                htmlReportCoinQrcodeinfoVO.setUrl(qrcodeUrl);
                log.info("用户订阅报告 二维码链接 结束：openId{},耗时：{}s", htmlReportGenerateBO.getOpenId(), (System.currentTimeMillis() - htmlReportCoinQrcodeinfoStartTime) / 1000.0);
                return htmlReportCoinQrcodeinfoVO;
            });


            // 重新查询基础信息
            Future<HtmlReportCoinBasicInfoVO> coinBasicInfoAgainFuture = CompletableFuture.supplyAsync(() -> {
                long htmlReportGenerateStartTime = System.currentTimeMillis();
                HtmlReportCoinBasicInfoVO coinBasicInfoAgain = getCoinBasicInfoAgain(htmlReportGenerateBO.getBccId());
                log.info("用户订阅报告 重新查询基础信息 结束：openId{},已耗时：{}s", htmlReportGenerateBO.getOpenId(), (System.currentTimeMillis() - htmlReportGenerateStartTime) / 1000.0);
                return coinBasicInfoAgain;
            });


            // 重新加载折线图和top5
            Future<List<HtmlReportLineChartVO>> lineChartVOSFuture = CompletableFuture.supplyAsync(() -> {
                long lineChartStartTime = System.currentTimeMillis();
                List<HtmlReportLineChartVO> lineChartVOS = htmlReportParseHelper.parseLineChart(htmlReportGenerateBO.getBccId());
                log.info("用户订阅报告 重新加载折线图和top5 结束：openId{},已耗时：{}s", htmlReportGenerateBO.getOpenId(), (System.currentTimeMillis() - lineChartStartTime) / 1000.0);
                return lineChartVOS;
            });


            // 重新加载top5
            Future<List<HtmlReportCoinTodayRecommendVO>> todayRecommendVOSFuture = CompletableFuture.supplyAsync(() -> {
                long todayRecommendStartTime = System.currentTimeMillis();
                List<HtmlReportCoinTodayRecommendVO> todayRecommendVOS = htmlReportParseHelper.parseTodayRecommend(DateUtil.currentDate2Str("yyyyMMddHH"));
                log.info("用户订阅报告 重新加载top5 结束：openId{},已耗时：{}s", htmlReportGenerateBO.getOpenId(), (System.currentTimeMillis() - todayRecommendStartTime) / 1000.0);
                return todayRecommendVOS;
            });

            Future<List<BccNews>> BccNewsFuture = CompletableFuture.supplyAsync(() -> {
                long bccNewsListStartTime = System.currentTimeMillis();
                List<BccNews> bccNewsList = bccNewsService.queryCurrentNewsByBccId(htmlReportGenerateBO.getBccId());
                log.info("用户订阅报告 币的舆情信息 结束：openId{},已耗时：{}s", htmlReportGenerateBO.getOpenId(), (System.currentTimeMillis() - bccNewsListStartTime) / 1000.0);
                return bccNewsList;
            });

            htmlReportGenerateVO.setQrcodeinfo(htmlReportCoinQrcodeinfoFuture.get());
            htmlReportGenerateVO.setBasicInfo(coinBasicInfoAgainFuture.get());
            htmlReportGenerateVO.setLineChartVOList(lineChartVOSFuture.get());
            htmlReportGenerateVO.setTodayRecommendVOList(todayRecommendVOSFuture.get());
            htmlReportGenerateVO.setBccNewsList(BccNewsFuture.get());
        } catch (Exception e) {
            log.error("【生成报告异常】异常栈信息： {}", e);
            return null;
        }


        return htmlReportGenerateVO;
    }


    /**
     * 生成完成报告
     *
     * @param bccId
     * @return
     */
    public HtmlReportGenerateVO createCompleteReport(String bccId) {
        // 查询报告数据结构
        JSONObject jsonObject = htmlReportParseHelper.getJsonObject(bccId);
        if (jsonObject == null) {
            log.error("数据源无数据");
            return null;
        }
        // 币的报告折线数据
        List<HtmlReportLineChartVO> lineChartVOList = htmlReportParseHelper.parseLineChart(bccId);
        // 币的今日推荐
        List<HtmlReportCoinTodayRecommendVO> todayRecommendVOList = htmlReportParseHelper.parseTodayRecommend(DateUtil.currentDate2Str("yyyyMMddHH"));

        // 币的舆情信息
        List<BccNews> bccNewsList = bccNewsService.queryCurrentNewsByBccId(bccId);

        return HtmlReportParseHelper.Subscription.allReport(jsonObject, lineChartVOList, todayRecommendVOList, bccNewsList);
    }


    /**
     * 判断用户是否订阅
     *
     * @param openId
     * @param bccId
     * @return
     */
    private boolean checkUserIsSubscription(String openId, String bccId) {
        BccSubCoin bccSubCoin = subCoinDao.findByUserOpenIdAndBccId(openId, bccId);

        if (bccSubCoin == null) {
            log.warn("【判断用户是否订阅】没有查询到BccSubCoin,userSymbol为：{}，bccId为：{}", openId, bccId);
            return false;
        }

        // 未订阅
        Integer status = bccSubCoin.getStatus();
        if (status == 0) {
            return false;
        }

        // 判断订阅时间和当前时间进行比较，是否已经订阅过期
        long endTime = bccSubCoin.getEndTime();
        long currentTime = System.currentTimeMillis() / 1000;

        // 用户订阅过期
        if (currentTime > endTime) {
            return false;
        }

        return true;
    }


    @Override
    public boolean checkSubscribe(HtmlReportGenerateBO htmlReportGenerateBO) throws BusinessException {
        try {
            // 解析用户token
            BccUser bccUser = jwtParseTokenHelper.parseToken(htmlReportGenerateBO.getToken());
            if (bccUser == null) {
                log.error("解析用户token异常，解析出的用户对象为空，用户token为：{}", bccUser.getToken());
                throw new BusinessException(HtmlReportEnum.PARSE_USER_TOKEN.getCode(), HtmlReportEnum.PARSE_USER_TOKEN.getDescription());
            }
            return checkUserIsSubscription(bccUser.getOpenId(), htmlReportGenerateBO.getBccId());
        } catch (BusinessException e) {
            log.error("【检查用户是否订阅】异常栈信息:{}", e.getMessage());
            throw e;
        }
    }

    public HtmlReportCoinBasicInfoVO getCoinBasicInfoAgain(String bccId) {
        try {
            JSONObject jsonObject = htmlReportParseHelper.getJsonObject(bccId);
            if (jsonObject != null) {
                return HtmlReportParseHelper.parseBasicInfo(jsonObject);
            }
        } catch (Exception e) {
            log.error("【生成报告-再次取报告的基础信息失败】异常栈信息：{}", e.getMessage());
        }
        return null;
    }
}
